package org.qrd.openmayyam;

import java.io.*;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;


/**
 * Expand out a WAR file at a particular location.
 *
 * @author Adarsh
 * @author Sivaraman
 * @version $Revision: 1.0.1 $
 */

public class ExpandWar {

    // ------------ Initialise variables

    /**
     * The newlist contains the list of files that are listed on every check.
     * It includes the names of already extracted WAR files also.
     */

    File[] newlist;

    /**
     * list contains the list of the WARs that are not present in the old list.
     */

    File[] list;

    /**
     * oldlist contains the list of WAR files that were previously extracted.
     */

    File[] oldlist = null;

    /**
     * Instance of the Filter class. It may be used to filter out WAR files.
     */

    Filter filter;

    /**
     * This variable contains the
     */

    File file;

    /**
     * The constructor initialises the filter class with WAR extension.
     */

    public ExpandWar() {

        filter = new Filter("war");
    }


    /**
     * This method returns the string array containing a list of all the WAR files that have been expanded
     *
     * @param warurl This parameter contains the complete path from where to listen for WAR files
     *               <p/>
     *               If nothing is sent , "/home/adarsh/" is set as default   *
     */

    public String[] expandAll(String warurl) throws IOException {
        String wars[] = new String[10];
        
       
        if (warurl.length() == 0) return null;
        file = new File(warurl);
        newlist = file.listFiles(filter);

        String warfile = "";
        int period;
        // Get the new files

        list = getnewfiles(oldlist, newlist);
        // store this as a old list

        oldlist = newlist;

        System.out.println("old list"+oldlist);

        // if there are no new files

        if (list == null)
            return null;

        // Walk through the list of WAR files and expand them one by one

        for (int i = 0; i < list.length; i++) {
            period = list[i].getName().toString().lastIndexOf(".");
            warfile = list[i].getName().substring(0, period);

            // call the expand static method that expands the WAR file

            expand(list[i].toString(), warurl, warfile);
            System.out.println("WAR File Expanded : " + warfile);

            // store the expanded WAR file in the string array

            wars[i] = "/"+warfile;
        }
        return wars;
    }

    /**
     * Called by the expandAll() method to check for new WAR files
     *
     * @param oldlist2 The old list of WAR files that were present on previous check
     * @param newlist2 The list of WAR files that have obtained on this check
     * @return File array that contains the list of new files else null
     */

    private File[] getnewfiles(File[] oldlist2, File[] newlist2) {

        System.out.println("ExpandWar.getnewfiles()");
        int k = 0, number = 0;
        int flag = 0;
        if (oldlist2 == null)
            return newlist2;
        if (newlist2.length > oldlist2.length)
            number = newlist2.length - oldlist2.length;
        File[] list1 = new File[number];
        for (int i = 0; i < newlist2.length; i++) {
            flag = 0;
            for (int j = 0; j < oldlist2.length; j++) {
                // check if the file name is present in the old list

                if (oldlist2[j].getName().equals(newlist2[i].getName())) {
                    flag = 1;
                    break;
                }

            }
            // flag = 0 means that the file is a new one and not present in the old list

            if (flag == 0) {
                System.out.println(newlist2[i].toString());

                // Add the WAR file name to the list

                list1[k++] = newlist2[i];
            }

        }

        return list1;

    }

// -------- This method is not used .. just for testing purpose

    /**
     * This method may be used to Test the application as a standalone application.
     * The WAR file location is set as "/home/adarsh/sample.war" as default.
     */

   /* public static void main(String args[]) throws IOException {
        	//System.out.println("Please enter the complete WAR file location :  ");
        String warurl = "F:\\trail\\QRD\\OM\\wars\\myhello.war";
        //String warfile, pathname;
        int period;
        period = warurl.toString().lastIndexOf('/');
        if (period == -1)
            period = warurl.toString().lastIndexOf("\\");
        pathname = warurl.toString().substring(0, period + 1);
        warfile = warurl.toString().substring(period + 1, warurl.toString().lastIndexOf("."));
        //     System.out.println("period : " +period + " , pathname = "+pathname + " , war = "+ warfile);
        //     expand(warurl,pathname,warfile);
   
        new ExpandWar().expandAll(warfile);
        

    }*/

    /**
     * Expands the given WAR file
     *
     * @param warurl   The complete location of the WAR file in the system. Eg. "/home/adarsh/sample.war"
     * @param pathname The pathname of the WAR file to be expanded. Eg. "/home/adarsh/"
     * @param warfile  The name of the WAR file. Eg. "sample.war"
     * @throws IOException
     */

    public static void expand(String warurl, String pathname, String warfile) throws IOException {
        ;


        File docBase = new File(pathname, warfile);
        docBase.mkdir();
        JarFile jarFile = new JarFile(warurl);
        InputStream input = null;
        try {

            Enumeration<?> jarEntries = jarFile.entries();
           
            while (jarEntries.hasMoreElements()) {
                JarEntry jarEntry = (JarEntry) jarEntries.nextElement();
                String name = jarEntry.getName();
                int last = name.lastIndexOf('/');
                if (last >= 0) {
                    File parent = new File(docBase,
                            name.substring(0, last));
                    parent.mkdirs();
                }
                if (name.endsWith("/")) {
                    continue;
                }
                input = jarFile.getInputStream(jarEntry);

                File expandedFile = expand(input, docBase, name);
                long lastModified = jarEntry.getTime();
                if ((lastModified != -1) && (lastModified != 0) && (expandedFile != null)) {
                    expandedFile.setLastModified(lastModified);}
                input.close();
                input = null;
            }
        }
            catch (IOException e) {
            // If something went wrong, delete expanded dir to keep things 
            // clean
            deleteDir(docBase);
            throw e;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (Throwable t) {
                    ;
                }
                input = null;
            }
            if (jarFile != null) {
                try {
                    jarFile.close();
                } catch (Throwable t) {
                    ;
                }
                jarFile = null;
            }
        }

        return;

    }

    /**
     * A dummy method to check the working of the expand method
     *
     * @param warurl It requires the WAR url. Eg. "/home/adarsh/sample.war".
     */

    public static void init(String warurl) throws IOException {
        //	System.out.println("Please enter the complete WAR file location :  ");
        //String warurl="/home/adarsh/sample.war";
        //	String warurl=args[0];
        String warfile, pathname;
        int period;
        period = warurl.toString().lastIndexOf('/');
        if (period == -1)
            period = warurl.toString().lastIndexOf("\\");
        pathname = warurl.toString().substring(0, period + 1);
        warfile = warurl.toString().substring(period + 1, warurl.toString().lastIndexOf("."));
        //     System.out.println("period : " +period + " , pathname = "+pathname + " , war = "+ warfile);
        expand(warurl, pathname, warfile);


    }


    /**
     * Delete the specified directory, including all of its contents and
     * subdirectories recursively.
     *
     * @param dir File object representing the directory to be deleted
     */
    public boolean delete(File dir) {
        if (dir.isDirectory()) {
            return deleteDir(dir);
        } else {
            return dir.delete();
        }
    }


    /**
     * Delete the specified directory, including all of its contents and
     * subdirectories recursively.
     *
     * @param dir File object representing the directory to be deleted
     */
    public static boolean deleteDir(File dir) {

        String files[] = dir.list();
        if (files == null) {
            files = new String[0];
        }
        for (int i = 0; i < files.length; i++) {
            File file = new File(dir, files[i]);
            if (file.isDirectory()) {
                deleteDir(file);
            } else {
                file.delete();
            }
        }
        return dir.delete();

    }


    /**
     * Expand the specified input stream into the specified directory, creating
     * a file named from the specified relative path.
     *
     * @param input InputStream to be copied
     * @param docBase Document base directory into which we are expanding
     * @param name Relative pathname of the file to be created
     * @return A handle to the expanded File
     *
     * @exception IOException if an input/output error occurs
     */
    protected static File expand(InputStream input, File docBase, String name)
            throws IOException {

        File file = new File(docBase, name);
        BufferedOutputStream output = null;
        try {
            output =
                    new BufferedOutputStream(new FileOutputStream(file));
            byte buffer[] = new byte[2048];
            while (true) {
                int n = input.read(buffer);
                if (n <= 0)
                    break;
                output.write(buffer, 0, n);
            }
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    // Ignore
                }
            }
        }

        return file;
    }


}
